package bibliOnline.util.details;

import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Contiene i dati relativi ad un utente.
 * 
 * @author Luca Piacentini
 */
public class UserDetails implements Serializable 
{
    
    /**
     *  Tipo utente: Non registrato
     */
    public static final String USER = "USER";
    
    /**
     *  Tipo utente: Utilizzatore biblioteca
     */
    public static final String CUSTOMER = "CUSTOMER";
    
    /**
     *  Tipo utente: Bibliotecario
     */
    public static final String LIBRARIAN = "LIBRARIAN";
    
    
    /**
     * Definisce il nome della proprietà/attributo "username". Utile per l'encoding 
     * in formato JSON.
     */
    public static final String PROP_USERNAME = "username";
    private String username;
    
    /**
     * Definisce il nome della proprietà/attributo "password". Utile per l'encoding 
     * in formato JSON.
     */
    public static final String PROP_PASSWORD = "password";
    private String password;
    
    /**
     * Definisce il nome della proprietà/attributo "firstname". Utile per l'encoding 
     * in formato JSON.
     */
    public static final String PROP_FIRSTNAME = "firstname";
    private String firstname;
    
    /**
     * Definisce il nome della proprietà/attributo "lastname". Utile per l'encoding 
     * in formato JSON.
     */
    public static final String PROP_LASTNAME = "lastname";
    private String lastname;
    
    /**
     * Definisce il nome della proprietà/attributo "address". Utile per l'encoding 
     * in formato JSON.
     */
    public static final String PROP_ADDRESS = "address";
    private String address;
    
    /**
     * Definisce il nome della proprietà/attributo "email". Utile per l'encoding 
     * in formato JSON.
     */
    public static final String PROP_EMAIL = "email";
    private String email;
    
    /**
     * Definisce il nome della proprietà/attributo "type". Utile per l'encoding 
     * in formato JSON.
     */
    public static final String PROP_TYPE = "type";
    private String type;

    /**
     *  Costruttore che genera un oggetto vuoto ( i cui campi interni non sono
     *  inizializzati)
     */
    public UserDetails() {
    }

    /**
     *  Costruttore che prevede il contestuale inserimento dei dati 
     * 
     * @param username String contenente il nome utente dell'utente
     * @param password String contenente la password dell'utente
     * @param firstname String contenente il nome dell'utente
     * @param lastname String contenente il cognome dell'utente
     * @param address String contenente l'indirizzo dell'utente
     * @param email String contenente la mail dell'utente
     * @param type String contenente il tipo di utente
     * 
     * @see String
     */
    public UserDetails(String username, String password, String firstname,
            String lastname, String address, String email, String type) {
        this.username = username;
        this.password = password;
        this.firstname = firstname;
        this.lastname = lastname;
        this.address = address;
        this.email = email;
        this.type = type;
    }

    /**
     *  Ritorna l'indirizzo dell'utente
     *      
     * @return String contenente l'indirizzo dell'utente
     * 
     * @see String
     */
    public String getAddress() {
        return address;
    }

    /**
     *  Setta l'indirizzo dell'utente
     * 
     * @param address String contenente l'indirizzo dell'utente
     * 
     * @see String
     */
    public void setAddress(String address) {
        this.address = address;
    }
    
   /**
     *  Setta l'indirizzo dell'utente controllandone la correttezza. Se viene rilevato
     *  un non rispetto delle regole viene generata un eccezione.
     * 
     * @param address String contenente l'indirizzo dell'utente
     * 
     * @see String
     */
    public void checkAndSetAddress(String address) throws Exception
    {
        
        if(address == null || address.equals(""))
            throw new Exception("Indirizzo: attributo obbligatorio");
        
        if(address.length() < 5)
            throw new Exception("Indirizzo: lunghezza minima 5 caratteri");
        
        if(address.length() > 40)
            throw new Exception("Indirizzo: lunghezza massima 30 caratteri");
        
        String description = "da 1 a 50 lettere o apici, poi 0 o piu' coppie spazio-lettere";
        String regex = "[a-zA-z']{1,50}( [a-zA-z']{1,50}){0,}";

        Pattern pattern;
        pattern = Pattern.compile(regex);
        Matcher matcher;
        matcher = pattern.matcher(address);
        if(matcher.matches() == false)
            throw new Exception("Indirizzo: "+ description);
        
        this.address = address;
    }

    /**
     *  Ritorna la email dell'utente
     *      
     * @return String contenente la email dell'utente
     * 
     * @see String
     */
    public String getEmail() {
        return email;
    }

    /**
     *  Setta la email dell'utente
     * 
     * @param email String contenente la mail dell'utente
     * 
     * @see String
     */
    public void setEmail(String email) {
        this.email = email;
    }
    
   /**
     *  Setta la email dell'utente controllandone la correttezza. Se viene rilevato
     *  un non rispetto delle regole viene generata un eccezione.
     * 
     * @param email String contenente la email dell'utente
     * 
     * @see String
     */
    public void checkAndSetEmail(String email) throws Exception
    {
        
        if(email == null || email.equals(""))
            throw new Exception("Email: attributo obbligatorio");
               
        if(email.length() > 40)
            throw new Exception("Email: lunghezza massima 40 caratteri");
        
        String description = "Mail non validata con successo";
        String regex = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

        Pattern pattern;
        pattern = Pattern.compile(regex);
        Matcher matcher;
        matcher = pattern.matcher(email);
        if(matcher.matches() == false)
            throw new Exception("Email: "+ description);
        
        this.email = email;
    }
    
    /*
        ^			# start of the line
        [_A-Za-z0-9-]+          #  must start with string in the bracket [ ], must contains one or more (+)
        (			# start of group #1
        \\.[_A-Za-z0-9-]+	# follow by a dot "." and string in the bracket [ ], must contains one or more (+)
        )*			# end of group #1, this group is optional (*)
        @			# must contains a "@" symbol
        [A-Za-z0-9]+            # follow by string in the bracket [ ], must contains one or more (+)
        (			# start of group #2 - first level TLD checking
        \\.[A-Za-z0-9]+         # follow by a dot "." and string in the bracket [ ], must contains one or more (+)
        )*              	# end of group #2, this group is optional (*)
        (			# start of group #3 - second level TLD checking
        \\.[A-Za-z]{2,}         # follow by a dot "." and string in the bracket [ ], with minimum length of 2
        )			# end of group #3
        $			#end of the line
     
     */

    /**
     *  Ritorna il nome dell'utente
     *      
     * @return String contenente il nome dell'utente
     * 
     * @see String
     */
    public String getFirstname() {
        return firstname;
    }

    /**
     *  Setta il nome dell'utente
     * 
     * @param firstname String contenente il nome dell'utente
     * 
     * @see String
     */
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    /**
     *  Setta il nome dell'utente controllandone la correttezza. Se viene rilevato
     *  un non rispetto delle regole viene generata un eccezione.
     * 
     * @param firstname String contenente il nome dell'utente
     * 
     * @see String
     */
    public void checkAndSetFirstname(String firstname) throws Exception
    {
        if(firstname == null || firstname.equals(""))
            throw new Exception("Nome: attributo obbligatorio");
        
        if(firstname.length() < 5)
            throw new Exception("Nome: lunghezza minima 5 caratteri");
        
        if(firstname.length() > 25)
            throw new Exception("Nome: lunghezza massima 25 caratteri");
        
        String description = "da 1 a 50 lettere o apici, poi 0 o piu' coppie spazio-lettere";
        String regex = "[a-zA-z']{1,50}( [a-zA-z']{1,50}){0,}";

        Pattern pattern;
        pattern = Pattern.compile(regex);
        Matcher matcher;
        matcher = pattern.matcher(firstname);
        if(matcher.matches() == false)
            throw new Exception("Nome: "+ description);
        
        this.firstname = firstname;
    }

    /**
     * Ritorna il cognome dell'utente
     *      
     * @return String contenente il cognome dell'utente
     * 
     * @see String
     */
    public String getLastname() {
        return lastname;
    }

    /**
     * Setta il cognome dell'utente
     *      
     * @param lastname String contenente il cognome dell'utente
     * 
     * @see String
     */
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    /**
     *  Setta il cognome dell'utente controllandone la correttezza. Se viene rilevato
     *  un non rispetto delle regole viene generata un eccezione.
     * 
     * @param lastname String contenente il cognome dell'utente
     * 
     * @see String
     */
    public void checkAndSetLastname(String lastname) throws Exception
    {
        if(lastname == null || lastname.equals(""))
            throw new Exception("Cognome: attributo obbligatorio");
        
        if(firstname.length() < 5)
            throw new Exception("Cognome: lunghezza minima 5 caratteri");
        
        if(lastname.length() > 25)
            throw new Exception("Cognome: lunghezza massima 25 caratteri");
        
        String description = "Da 1 a 50 lettere o apici, poi 0 o piu' coppie spazio-lettere";
        String regex = "[a-zA-z']{1,50}( [a-zA-z']{1,50}){0,}";

        Pattern pattern;
        pattern = Pattern.compile(regex);
        Matcher matcher;
        matcher = pattern.matcher(lastname);
        if(matcher.matches() == false)
            throw new Exception("Cognome: "+description);
        
        this.lastname = lastname;
    }

    
    /**
     *  Ritorna la password dell'utente
     *      
     * @return String contenente la password dell'utente
     * 
     * @see String
     */
    public String getPassword() {
        return password;
    }

   
    /**
     *  Setta la password dell'utente
     *      
     * @param password String contenente la password dell'utente
     * 
     * @see String
     */
    public void setPassword(String password) {
        this.password = password;
    }
    
    

    
    /**
     *  Setta la password dell'utente controllandone la correttezza. Se viene rilevato
     *  un non rispetto delle regole viene generata un eccezione.
     * 
     * @param password String contenente la password dell'utente
     * 
     * @see String
     */
    public void checkAndSetPassword(String password, String passwordCodificata) throws Exception
    {
        if(password == null || password.equals(""))
            throw new Exception("Password: attributo obbligatorio");
        
        if(password.length() < 3)
            throw new Exception("Password: lunghezza minima 3 caratteri");
        
        if(password.length() > 25)
            throw new Exception("Password: lunghezza massima 25 caratteri");
        
//	e' bello e ben fatto ma rompe le scatole per il debug!
//        String description = "Obbigliatorie lettere maiusc. e minusc., cifre e almeno 1 di '@#$%'";
//        String regex = "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{3,25})";

	String description = "Non sono ammessi caratteri speciali (esclusi _ e hypen)";
        String regex = "^[a-zA-Z0-9_-]{3,25}$";

        Pattern pattern;
        pattern = Pattern.compile(regex);
        Matcher matcher;
        matcher = pattern.matcher(password);
        if(matcher.matches() == false)
            throw new Exception("Password: "+description);
        
        this.password = passwordCodificata;
    }
    
    /*  (			#   Start of group
        (?=.*\d)		#   must contains one digit from 0-9
        (?=.*[a-z])		#   must contains one lowercase characters
        (?=.*[A-Z])		#   must contains one uppercase characters
        (?=.*[@#$%])		#   must contains one special symbols in the list "@#$%"
        .                       #   match anything with previous condition checking
        {6,20}                  #   length at least 6 characters and maximum of 20	
        )                       #   End of group
     */

    
    /**
     *  Ritorna il tipo di utente
     *      
     * @return String contenente il tipo di utente
     * 
     * @see USER,CUSTOMER,LIBRARIAN
     */
    public String getType() {
        return type;
    }

    /**
     *  Setta il tipo di utente
     *      
     * @param type String contenente il tipo di utente
     * 
     * @see USER,CUSTOMER,LIBRARIAN
     */
    public void setType(String type) {
        this.type = type;
    }

    /**
     * Ritorna l'username dell'utente
     *      
     * @return String contenente il nome utente dell'utente
     * 
     * @see String
     */
    public String getUsername() {
        return username;
    }

    /**
     *  Setta l'username dell'utente  
     * 
     * @param username String contenente il nome utente dell'utente
     * 
     * @see String
     */
    public void setUsername(String username) {
        this.username = username;
    }
    
    
    /**
     *  Setta l'username dell'utente controllandone la correttezza. Se viene rilevato
     *  un non rispetto delle regole viene generata un eccezione.
     * 
     * @param username String contenente l'username dell'utente
     * 
     * @see String
     */
    public void checkAndSetUsername(String username) throws Exception
    {
        if(username == null || username.equals(""))
            throw new Exception("Username: attributo obbligatorio");
        
        if(username.length() < 3)
            throw new Exception("Username: lunghezza minima 3 caratteri");
        
        if(username.length() > 25)
            throw new Exception("Username: lunghezza massima 25 caratteri");
        
        String description = "Non sono ammessi caratteri speciali (esclusi _ e hypen)";
        String regex = "^[a-zA-Z0-9_-]{3,25}$";

        Pattern pattern;
        pattern = Pattern.compile(regex);
        Matcher matcher;
        matcher = pattern.matcher(username);
        if(matcher.matches() == false)
            throw new Exception("Username: "+description);
        
        this.username = username;
    }
    
    /*  ^                    # Start of the line
        [a-z0-9_-]	     # Match characters and symbols in the list, a-z, 0-9, underscore, hyphen
        {3,15}               # Length at least 3 characters and maximum length of 15 
        $                    # End of the line
    */
}
